package com.ruoyi.multab.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.mathworks.toolbox.javabuilder.MWException;
import com.mathworks.toolbox.javabuilder.MWNumericArray;
import com.ruoyi.multab.domain.MulModelResult;
import com.ruoyi.multab.service.IMulModelCalcService;
import com.ruoyi.multab.websocket.WebSocketServer;

import RAGA_PP.RAGA_PPC;

/**
 * 仿真模型Service业务层处理
 * 
 * @author zhouwc
 * @date 2020-09-20
 */
@Service("calcServiceImpl1")
public class MulModelCalcServiceImpl1 implements IMulModelCalcService {
	
    private static final Logger log = LoggerFactory.getLogger(MulModelCalcServiceImpl1.class);
    final static int DATA_PROCESS_OUT_NUM = 2;/**预处理函数输出参数数量*/
    final static int DATA_RAGA_OUT_NUM = 7;/**RAGA函数输出参数数量*/
    
    @Autowired
    private WebSocketServer webSocketServer;

	@Override
	public void execCalc(String sessionId, Map<String, String> calcParam, Double[][] inputValues) {

		try {
			// 1.输入参数准备
			double N = MapUtils.getDoubleValue(calcParam, "N");;//TODO 参数含义是?
			// 原始数据 inputValues

			MWNumericArray x = new MWNumericArray(inputValues);

			double Pc = MapUtils.getDoubleValue(calcParam, "Pc");
			double Pm = MapUtils.getDoubleValue(calcParam, "Pm");
			double M = MapUtils.getDoubleValue(calcParam, "M");
			double DaiNo = MapUtils.getDoubleValue(calcParam, "DaiNo");
			double Ci = MapUtils.getDoubleValue(calcParam, "Ci");
			double ads = MapUtils.getDoubleValue(calcParam, "ads");
			double ac = MapUtils.getDoubleValue(calcParam, "ac");
			double exV = MapUtils.getDoubleValue(calcParam, "exV");
			double par_Q = MapUtils.getDoubleValue(calcParam, "par_Q");
			double coe_Q = MapUtils.getDoubleValue(calcParam, "coe_Q");
			int Run_No = MapUtils.getIntValue(calcParam, "Run_No");
			
			String Max_max_No_str = calcParam.get("Max_max_No");
			int[] Max_max_No = getIntArrayFromStr(Max_max_No_str);
			String Min_min_No_str = calcParam.get("Min_min_No");
			int[] Min_min_No = getIntArrayFromStr(Min_min_No_str);

			RAGA_PPC ppc = new RAGA_PPC();
			// 2.执行预处理函数
			Object[] dataprocess = ppc.dataprocess(DATA_PROCESS_OUT_NUM, x, Max_max_No, Min_min_No);
			Object xx = dataprocess[0];
			Object n = dataprocess[1];
			log.info("xx={}",xx);
			log.info("n={}",n);

			// 3.设置随机规则
			// ppc.suijikongzhi();
			// 4.根据输入执行循环
			List<Object[]> list = new ArrayList<Object[]>();
			//计算最大a值和循环次数
			MulModelResult modelResult = new MulModelResult();
			
			for (int i = 1; i <= Run_No; i++) {
				try {
					log.info("第" + i + "次循环开始=================");

					Object[] raga = ppc.RAGA(7, N, n, xx, Pc, Pm, M, DaiNo, Ci, ads, ac, exV, par_Q, coe_Q);
					list.add(raga);
					//1:为目标函数值，为一行向量，列数等于Run_No；
					log.info("第" + i + "次循环输出1=" + raga[0]);// a 单个值,需要求最大
					getMaxRagaValuea(modelResult,i,raga[0].toString());
					//2:b为目标函数a对应的投影方向，为一n列Run_No行的矩阵；
					log.info("第" + i + "次循环输出2=" + raga[1]);// b Run_No行,n列
					//3:t3记录RAGA运行Run_No次中每次的时间;
					log.info("第" + i + "次循环输出3=" + raga[2]);
					//4:index_max为运行Run_No次中，目标函数最大值对应的加速次数向量
					log.info("第" + i + "次循环输出4=" + raga[3]);
					//5:fv1_max为运行Run_No次中，目标函数最大值时对应每次加速目标函数最大值向量；
					log.info("第" + i + "次循环输出5=" + raga[4]);// t3 每次multab运行的时间
					//6:
					log.info("第" + i + "次循环输出6=" + raga[5]);// index 元胞(三位数组)
					//7:
					log.info("第" + i + "次循环输出7=" + raga[6]);// fv1 元胞
					
					webSocketServer.sendInfo(sessionId, "chart-" + i + "-" + raga[0]);

					log.info("第" + i + "次循环结束=================");
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				
				//TODO 设置50ms时间将数据刷新到页面
//				int y = new Random().nextInt(1000);
//				webSocketServer.sendInfo(sessionId, (i+1)+"-"+y);
//				try {
//					Thread.sleep(500);
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
			}

			// 5.计算循环结果
			//得到最大a值和循环次数
			log.info("modelResult="+modelResult.toString());
			int ragaMaxAindex = modelResult.getRagaMaxAindex();
			Object[] targetobj = list.get(ragaMaxAindex-1);
			
			MWNumericArray b = (MWNumericArray) targetobj[1];
			MWNumericArray index = (MWNumericArray) targetobj[5];
			MWNumericArray fv1 = (MWNumericArray) targetobj[6];

			//[[0.36632357597920573, 0.29869448503148044, 0.3063613133949941, 0.2299097336916198, 0.2957480076973809, 0.2840764341844491, 0.2747337993244982, 0.28149335726480157, 0.3016555699027554, 0.4039172731551812, 0.13687590482356218, 0.18468667353975896]]
			Object doubleArrayB = b.toDoubleArray();
			//[[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0]]
			Object doubleArrayIndex = index.toDoubleArray();
			//[[1.2748645718363232, 1.484953573798579, 1.4587423504604637, 1.5922634475199204, 1.5925454697535593, 1.5925454697535593, 1.592060266068194, 1.574746941371142, 1.574746941371142, 1.497607219078295, 1.6528748792352919, 1.5297989838071007, 1.3705062590230705, 1.288742139093374, 1.5808256887491892, 1.5292267068908325, 1.3761966883665395, 1.3761966883665395, 1.2875788882719255, 1.3204816073948675]]
			Object doubleArrayFv1 = fv1.toDoubleArray();
			
			log.info(JSONObject.toJSONString(doubleArrayB));
			log.info(JSONObject.toJSONString(doubleArrayIndex));
			log.info(JSONObject.toJSONString(doubleArrayFv1));
			
			modelResult.setDoubleArrayB(doubleArrayB);
			modelResult.setDoubleArrayIndex(doubleArrayIndex);
			modelResult.setDoubleArrayFv1(doubleArrayFv1);
			
			
			webSocketServer.sendInfo(sessionId, "modelResult-" + JSONObject.toJSONString(modelResult));


		} catch (MWException e) {
			e.printStackTrace();
		}

	}
	private void getMaxRagaValuea(MulModelResult modelResult, int newIndex, Object newValue) {
		if(modelResult.getRagaMaxAvalue() == null) {
			//初始数据处理
			modelResult.setRagaMaxAvalue(newValue);
			modelResult.setRagaMaxAindex(newIndex);
			
			return;
		}
		if(newValue == null) {
			return;
		}
		
		BigDecimal oldInt = new BigDecimal(modelResult.getRagaMaxAvalue().toString());
		BigDecimal newInt = new BigDecimal(newValue.toString());
		
		if(newInt.compareTo(oldInt) > 0) {
			modelResult.setRagaMaxAvalue(newValue);
			modelResult.setRagaMaxAindex(newIndex);
		}
		return;
		
	}

	private int[] getIntArrayFromStr(String max_max_No_str) {
		if(StringUtils.isBlank(max_max_No_str)) {
			return new int[0];
		}
		String[] split = max_max_No_str.split(",");
		int[] intarray = new int[split.length];
		for(int i = 0;i<split.length;i++) {
			intarray[i] = Integer.parseInt(split[i]);
		}
		return intarray;
	}
	public static void main(String[] args) {
		MulModelResult modelResult = new MulModelResult();
		String jsonString = JSONObject.toJSONString(modelResult);
		System.out.println(jsonString);
		
	}
}
